#include "StdAfx.h"
#include "DatTickSrc.h"

#include "GenTickTechDlg.h"

CDatTickSrc::CDatTickSrc(void)
	: m_sRoot(_T(""))
	, m_pTickDats(NULL)
	, m_nTickCount(0)
	, m_nTickTotal(0)
	, m_nCurDate(0)
	, m_bInit(false)
	, m_pLTGSFQDats(NULL)
	, m_nLTCount(0)
	, m_nFQLTTotal(0)
	, m_nFQCount(0)
	, m_AllocCount(0)
{
}


CDatTickSrc::~CDatTickSrc(void)
{
}


int CDatTickSrc::Init(const char * sRoot)
{
	m_sRoot = sRoot;
	return 0;
}


int CDatTickSrc::GetDirFileToAry(CArray<CString ,CString &> & ary, const CString & dir, char * Filter)
{
	CString strFilter;
	WIN32_FIND_DATA FindFileData;
	strFilter = dir + "\\*.*";
	HANDLE hFind = FindFirstFile(strFilter,&FindFileData);
	BOOL bRet = true;
	CString FileName;
	CString FilterStr = Filter;

	GetOneDirFileToAry(ary, dir, Filter );

	if(hFind != INVALID_HANDLE_VALUE)
	{
		while(bRet)
		{
			FileName = dir + "\\" + FindFileData.cFileName;
			if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				if(strcmp(FindFileData.cFileName,".") != 0  &&  strcmp(FindFileData.cFileName,"..") != 0 )
				{
					GetDirFileToAry(ary,FileName,Filter); 
				}
			}
			bRet = FindNextFile(hFind,&FindFileData);
		}
	}
	return 0;
}


int CDatTickSrc::GetOneDirFileToAry(CArray<CString ,CString &> & ary, const CString & dir, char * Filter)
{
	CString strFilter;
	WIN32_FIND_DATA FindFileData;
	strFilter = dir + "\\" + Filter;
	CFileFind FileFind;
	HANDLE hFind = FindFirstFile(strFilter,&FindFileData);
	BOOL bRet = true;
	int pos;
	CString FileName,sPath,sFile;

	if(hFind != INVALID_HANDLE_VALUE)
	{
		while(bRet)
		{
			FileName = dir + "\\" + FindFileData.cFileName;
			if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			{
				sPath = FileName.Left( FileName.GetLength()-12 );
				sFile = FileName.Right( 12 );

				ary.Add( FileName );
			}
			bRet = FindNextFile(hFind,&FindFileData);
		}
	}
	return 0;
}


//D:\data\Stk_TradeByTrade\Stk_TradeByTrade_2010\201009\20100927
int CDatTickSrc::LoadTickDat(int nDate, int flag)
{
	int nYear	= nDate/10000;
	int nMonth	= (nDate%10000)/100;
	int nDay	= nDate%100;
	CArray<CString ,CString &> ary;

	CString sPath;

	sPath.Format("%s\\Stk_TradeByTrade_%d\\%d%02d\\%d", m_sRoot, nYear, nYear, nMonth, nDate );

	GetOneDirFileToAry( ary, sPath, "*.csv" );

	int i,nCode;
	FILE *fp;
	TickDat dat;
	char sBuf[1024];

	m_nCurDate		= nDate;
	m_nTickCount	= 0;

	dat.nDate	= nDate;

	CGenTickTechDlg *pMain	= (CGenTickTechDlg *)::AfxGetMainWnd();

	int j;



	//    ������е����̼۲�����ȫ�����һ�ʽ��׵ĳɽ��۸񣬶���һ����Ȩƽ���ۣ�Ҳ���ѵ������̼ۡ��������̼�Ϊ���ո�֤ȯ���һ�ʽ���ǰһ�������н��׵ĳɽ�����Ȩƽ���ۣ������һ�ʽ��ף���
	//    �����޳ɽ��ģ���ǰ���̼�Ϊ�������̼ۡ�
	//    �������̼���ͨ����������Ӽ��Ͼ��۵ķ�ʽ���������̼��Ͼ��۲��ܲ������̼۵ģ��Ե��ո�֤ȯ���һ�ʽ���ǰһ�������н��׵ĳɽ�����Ȩƽ����(�����һ�ʽ���)Ϊ���̼ۡ�
	//    �����޳ɽ��ģ���ǰ���̼�Ϊ�������̼ۡ�

	for( i=0; i<ary.GetSize(); i++ )
	{
		sPath = ary.GetAt(i);
		dat.nCode = atoi(sPath.Right(10).Left(6));

		if( (i%100)==0 )
		{
			pMain->m_sOutput.Format("��ʼ����%d����ʳɽ�����...%d-%d, %06d", nDate, i, ary.GetSize(), dat.nCode );
			pMain->UpdateData( false );
		}
		fopen_s( &fp, sPath, "r" );
		double dSum = 0;
		double dVol = 0;
		while( fgets( sBuf, 1023, fp ) )
		{
			if( AnalyseLine( sBuf, dat )==0 )
			{
				if( flag==0 && dat.nTime<121500 )
				{
					AddTickDat( dat);
				}else if(  flag==1 && dat.nTime>121500 )
				{
					AddTickDat( dat);
					if( dat.nTime>=145900 )
					{
						dSum += dat.nPrice * dat.dVol;
						dVol += dat.dVol;
					}
				}
			}
		}
		fclose( fp );
		if( flag==1 && dSum>1 && dat.nCode>=600000 )
		{
			dat.dTurnRate	= 0;
			dat.dVol		= 0;
			dat.nPrice		= dSum / dVol;
			dat.nTime		= 151501;
			AddTickDat( dat);
		}
	}
	if( m_nTickCount>0 )
	{
		qsort( m_pTickDats, m_nTickCount, sizeof(TickDat), compare0 );
	}

	return 0;
}


int CDatTickSrc::AnalyseLine(char * sBuf, TickDat & dat)
{
	char *pStr,*pStr1;
	//92501	11.58	B	100
	pStr = strstr( sBuf, "," );
	if( !pStr )
	{
		return -1;
	}
	*pStr = 0;
	dat.nTime = atoi( sBuf );
	if( dat.nTime>151500 )
	{
		CString tmpStr;

		tmpStr.Format( "ʱ�����%06d-%d", dat.nCode, dat.nTime );
		MessageBox( NULL, tmpStr, "ERR", MB_OK );
	}

	pStr1 = strstr( pStr+1, "," );
	if( !pStr1 )
	{
		return -1;
	}
	*pStr1 = 0;
	dat.nPrice = atof( pStr+1 )*10000;

	pStr = strstr( pStr1+1, "," );
	if( !pStr )
	{
		return -1;
	}

	dat.dVol = atoi( pStr+1 );
	return 0;
}



int CDatTickSrc::AddTickDat(TickDat & dat)
{
	if( m_nTickCount>=m_nTickTotal )
	{
		m_nTickTotal += 15000000;
		m_pTickDats = (TickDat *)realloc( m_pTickDats, sizeof(TickDat) * m_nTickTotal );
		m_AllocCount++;
	}

	if( m_pTickDats==NULL )
	{
		MessageBox(NULL, "�����ڴ�ʧ�ܣ�", "����Tick����", MB_OK );
		exit(0);
	}

	if( m_nTickCount==0 )
	{
		memcpy( &m_pTickDats[m_nTickCount], &dat, sizeof(TickDat) );
		m_nTickCount++;
		return 0;
	}
	if( m_pTickDats[m_nTickCount-1].nCode==dat.nCode &&
		m_pTickDats[m_nTickCount-1].nDate==dat.nDate &&
		m_pTickDats[m_nTickCount-1].nPrice==dat.nPrice )
	{
		m_pTickDats[m_nTickCount-1].dVol	+= dat.dVol;
	}else
	{
		memcpy( &m_pTickDats[m_nTickCount], &dat, sizeof(TickDat) );
		m_nTickCount++;
	}

	return 0;
}


int CDatTickSrc::compare0(const void * arg1, const void * arg2)
{
	TickDat *pDat1 = (TickDat *)arg1;
	TickDat *pDat2 = (TickDat *)arg2;

	if( pDat1->nCode<pDat2->nCode )
	{
		return -1;
	}else if( pDat1->nCode>pDat2->nCode )
	{
		return 1;
	}
	if( pDat1->nTime<pDat2->nTime )
	{
		return -1;
	}else if( pDat1->nTime>pDat2->nTime )
	{
		return 1;
	}

	return 0;
}


//SELECT trade_date,stock_code,factor_pre FROM day_stocka_wind_full
//select trade_date,stock_code,float_pre,float_recent from share_profit_change where stock_code='%s' order by trade_date
/*int CDatTickSrc::LoadLTGS(void)
{
	if( !m_bInit )
	{
		return -1;
	}

	m_nLTCount = 0;
	CTickBackTrackingDlg *pMain	= (CTickBackTrackingDlg *)::AfxGetMainWnd();

	char strSQL[1024] = { 0 }; 

	pMain->m_sOutput.Format("��ʼ������ͨ�ɱ�����..." );
	pMain->UpdateData( false );

	//share_profit_change  ��¼�ɱ��仯�����ݿ⣬trade_date,stock_code,float_pre,float_recent
	sprintf(strSQL, "select trade_date,stock_code,float_pre,float_recent from share_profit_change order by stock_code,trade_date" );  
	sql::ResultSet *result;
	try{
		// ��ѯ
		result = m_stmt->executeQuery(strSQL);

		SQLString sqlStr;
		CString tmpStr;
		int nCode = 0;

		while( result->next())
		{
			if( m_nLTCount>=m_nFQLTTotal )
			{
				m_nFQLTTotal += 20000;
				m_pLTGSFQDats = (LTGS_FQ *)realloc( m_pLTGSFQDats, sizeof(LTGS_FQ)*m_nFQLTTotal );
			}
			sqlStr = result->getString(2);
			tmpStr = sqlStr.c_str();
			m_pLTGSFQDats[m_nLTCount].nCode		= atoi( tmpStr );
			if( nCode!=m_pLTGSFQDats[m_nLTCount].nCode )
			{
				nCode = m_pLTGSFQDats[m_nLTCount].nCode;
				m_pLTGSFQDats[m_nLTCount].nDate		= 0;
				m_pLTGSFQDats[m_nLTCount].Flag		= 1;
				sqlStr = result->getString(3);
				tmpStr = sqlStr.c_str();
				m_pLTGSFQDats[m_nLTCount].dFQ_LTGS	= atof(tmpStr);
				m_nLTCount++;
			}
			m_pLTGSFQDats[m_nLTCount].nCode = m_pLTGSFQDats[m_nLTCount-1].nCode;
			sqlStr = result->getString(1);
			tmpStr = sqlStr.c_str();//"2017-01-04 00:00:00
			m_pLTGSFQDats[m_nLTCount].nDate	= atoi(tmpStr.Left(4))*10000+atoi(tmpStr.Mid(5,2))*100+atoi(tmpStr.Mid(8,2));

			sqlStr = result->getString(4);
			tmpStr = sqlStr.c_str();//"2017-01-04 00:00:00
			m_pLTGSFQDats[m_nLTCount].dFQ_LTGS	= atof(tmpStr);
			m_pLTGSFQDats[m_nLTCount].Flag		= 1;
			m_nLTCount++;
		}
		if( result )
		{
			delete result;
		}

		m_nFQCount = m_nLTCount;
		pMain->m_sOutput.Format("��ʼ���ظ�Ȩ��������..." );
		pMain->UpdateData( false );

		sprintf(strSQL, "select trade_date,stock_code,factor_basic_formula from ex_dividend_wind where factor_basic_formula is not NULL order by stock_code,trade_date" ); 
		// ��ѯ
		result = m_stmt->executeQuery(strSQL);

		nCode = 0;
		double tmpFQFactor;
		int nCodeStart,i;
		while( result->next())
		{
			if( m_nFQCount>=m_nFQLTTotal )
			{
				m_nFQLTTotal += 20000;
				m_pLTGSFQDats = (LTGS_FQ *)realloc( m_pLTGSFQDats, sizeof(LTGS_FQ)*m_nFQLTTotal );
			}
			sqlStr = result->getString(2);
			tmpStr = sqlStr.c_str();
			m_pLTGSFQDats[m_nFQCount].nCode		= atoi( tmpStr );
			if( nCode!=m_pLTGSFQDats[m_nFQCount].nCode )
			{
				nCode = m_pLTGSFQDats[m_nFQCount].nCode;
				nCodeStart	= m_nFQCount;
			}
			sqlStr = result->getString(3);
			tmpStr = sqlStr.c_str();//"2017-01-04 00:00:00
			tmpFQFactor	= atof(tmpStr);

			sqlStr = result->getString(1);
			tmpStr = sqlStr.c_str();//"2017-01-04 00:00:00
			m_pLTGSFQDats[m_nFQCount].nDate		= atoi(tmpStr.Left(4))*10000+atoi(tmpStr.Mid(5,2))*100+atoi(tmpStr.Mid(8,2));
			m_pLTGSFQDats[m_nFQCount].Flag		= 0;
			m_pLTGSFQDats[m_nFQCount].dFQ_LTGS	= tmpFQFactor;

			for( i=nCodeStart; i<m_nFQCount; i++ )
			{
				m_pLTGSFQDats[i].dFQ_LTGS	*= tmpFQFactor;
			}
			m_nFQCount++;
		}
		if( result )
		{
			delete result;
		}
	}catch (sql::SQLException &e) {

        return -1;
	}
	return 0;
}
*/

int CDatTickSrc::InitMYSQL(void)
{
	m_bInit	= false;
	 try { 
        m_driver = sql::mysql::get_driver_instance();
        m_conn = m_driver->connect("tcp://192.168.31.181:3306", "developer02", "developer02");
        m_stmt = m_conn->createStatement();
        m_stmt->execute("USE stock");
		m_stmt->execute("set character set gbk");
		m_bInit = true;

    } catch (sql::SQLException &e) {
        /*
          The MySQL Connector/C++ throws three different exceptions:

          - sql::MethodNotImplementedException (derived from sql::SQLException)
          - sql::InvalidArgumentException (derived from sql::SQLException)
          - sql::SQLException (derived from std::runtime_error)
        */

        return -1;
    }

	return 0;
}

/*
double CDatTickSrc::GetFQFactor(int nCode, int nDate)
{
	int i;
	double tmpFQ = 1;

	for( i=m_nLTCount; i<m_nFQCount; i++ )
	{
		if( m_pLTGSFQDats[i].nCode<nCode )
		{
			continue;
		}else if( m_pLTGSFQDats[i].nCode>nCode )
		{
			break;
		}
		if( m_pLTGSFQDats[i].nDate>nDate )
		{
			tmpFQ = m_pLTGSFQDats[i].dFQ_LTGS;
			break;
		}else
		{
			tmpFQ = 1;
		}
	}
	return tmpFQ;
}


double CDatTickSrc::GetLTGS(int nCode, int nDate)
{
	int i;
	double tmpFQ = 50000000.0;

	for( i=0; i<m_nLTCount; i++ )
	{
		if( m_pLTGSFQDats[i].nCode<nCode )
		{
			continue;
		}else if( m_pLTGSFQDats[i].nCode>nCode )
		{
			break;
		}
		if( m_pLTGSFQDats[i].nDate<=nDate )
		{
			tmpFQ = m_pLTGSFQDats[i].dFQ_LTGS;
		}else
		{
			break;
		}
	}
	return tmpFQ;
}
*/